package com.yingxin.yx.framework.render.aop;

import com.yingxin.yx.framework.commons.activiti.dto.ActivitiInstanceDto;
import com.yingxin.yx.framework.commons.activiti.enums.FormKey;
import com.yingxin.yx.framework.commons.constant.CommonConst;
import com.yingxin.yx.framework.commons.vo.CommonRespVo;
import com.yingxin.yx.framework.redis.lock.RedisLockSupport;
import com.yingxin.yx.framework.render.core.*;
import com.yingxin.yx.framework.render.core.model.Column;
import com.yingxin.yx.framework.render.core.model.Content;
import com.yingxin.yx.framework.render.core.model.Form;
import com.yingxin.yxerp.module.common.BusinessType;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;
import java.util.stream.Collectors;

@Aspect
@Component
@Order(1)
public class RenderAop {

    @Autowired
    private RedisLockSupport redisLockSupport;

    @Pointcut("@annotation(com.yingxin.yx.framework.render.core.RenderApi)")
    public void logPoint() {
    }


    @Around("logPoint()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        Object result;
        result = joinPoint.proceed();
        if (result instanceof CommonRespVo) {
            CommonRespVo vo = (CommonRespVo) result;
            // RenderForm
            RenderForm renderForm = (RenderForm) findAnnotation(result.getClass().getAnnotations(), RenderForm.class);
            if (renderForm == null) {
                return result;
            }
            Form form = new Form();
            form.setName(renderForm.name());
            String filterValue = getFilterValue(result.getClass(), result);
            // addMainContent
            addMainContent(result.getClass(), renderForm, form, filterValue);
            // addOtherContent
            addOtherContent(result.getClass(), renderForm, form, filterValue);
            // activitiInstance
            ActivitiInstanceDto activitiInstance = vo.getActivitiInstance();
            // FormKey
            form.setFormKey(activitiInstance.getFormKey());
            // Operable
            /**
             * 是否在APP审核 默认都可以在app端审核
             * */
            /*
                form.setOperable(CommonConst.TRUE);
             */
            if (FormKey.COMMON.getKey().equals(activitiInstance.getFormKey())
                    || FormKey.READ_ONLY.getKey().equals(activitiInstance.getFormKey())
                    || FormKey.CANCEL_ONLY.getKey().equals(activitiInstance.getFormKey())
                    || FormKey.PRINT_LIMIT.getKey().equals(activitiInstance.getFormKey())
                    || "allowQuote".equals(activitiInstance.getFormKey())
                    || "confirmQuotation".equals(activitiInstance.getFormKey())
                    || "lastManagerApproval".equals(activitiInstance.getFormKey())
                    || FormKey.PRINT_INCOME.getKey().equals(activitiInstance.getFormKey())
                    || BusinessType.RZXS.getType().equals(activitiInstance.getBusinessType())
                    || BusinessType.SXXS.getType().equals(activitiInstance.getBusinessType())
                    || BusinessType.ZYXS.getType().equals(activitiInstance.getBusinessType())
                    || BusinessType.DXXS.getType().equals(activitiInstance.getBusinessType())
                    || BusinessType.FLXS.getType().equals(activitiInstance.getBusinessType())
                    || BusinessType.FYBX.getType().equals(activitiInstance.getBusinessType())
                    || BusinessType.QTHTFK.getType().equals(activitiInstance.getBusinessType())
                    || BusinessType.CLFKSQ.getType().equals(activitiInstance.getBusinessType())
                    || BusinessType.LJFKSQ.getType().equals(activitiInstance.getBusinessType())
                    || BusinessType.PSGL.getType().equals(activitiInstance.getBusinessType())
                    || BusinessType.BPCGFK.getType().equals(activitiInstance.getBusinessType())
                    || BusinessType.GCZJ.getType().equals(activitiInstance.getBusinessType())
                    || "finalApproval".equals(activitiInstance.getFormKey())
                    ) {
                        form.setOperable(CommonConst.TRUE); // 是true = 1 app能审核
            } else {
                form.setOperable(CommonConst.FALSE);  // 是false = 0 就是不能在app上审核
            }
            if (!renderForm.operable()) {
                form.setOperable(CommonConst.FALSE);
            }
            vo.setRenderForm(form);
        }
        return result;
    }

    /**
     * addMainContent
     */
    private void addMainContent(Class<?> clz, RenderForm renderForm, Form form, String filterValue) {
        List<Column> columns = getColumns(clz, filterValue);
        // 是否渲染父类
        if (renderForm.renderSuperClass()) {
            List<Column> superClassColumns = getColumns(clz.getSuperclass(), filterValue);
            columns.addAll(superClassColumns);
        }
        // columns 排序
        columns.sort(Comparator.comparing(Column::getSort));
        Map<Integer, List<Column>> groupingMap = columns.stream().collect(Collectors.groupingBy(Column::getGroup));
        TreeMap<Integer, List<Column>> treeMap = new TreeMap<>(groupingMap);
        List<Content> mainContentList = new ArrayList<>();
        for (Integer key : treeMap.keySet()) {
            Content content = new Content();
            content.setSort(key);
            content.setColumns(treeMap.get(key));
            for (Column column : content.getColumns()) {
                if (StringUtils.isNotBlank(column.getGroupName())) {
                    content.setName(column.getGroupName());
                    break;
                }
            }
            mainContentList.add(content);
        }
        form.setMainContentList(mainContentList);
    }

    /**
     * addOtherContent
     */
    private void addOtherContent(Class<?> clz, RenderForm renderForm, Form form, String filterValue) {
        List<Content> tableContentList = new ArrayList<>();
        List<Content> descContentList = new ArrayList<>();
        List<Content> imgContentList = new ArrayList<>();
        Field[] fields = clz.getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            RenderContent renderContent = (RenderContent) findAnnotation(field.getAnnotations(), RenderContent.class);
            if (renderContent != null) {
                List<Column> columns = getColumns(renderContent.className(), filterValue);
                // 是否渲染父类
                if (renderForm.renderSuperClass()) {
                    List<Column> superClassColumns = getColumns(renderContent.className().getSuperclass(), filterValue);
                    columns.addAll(superClassColumns);
                }
                // columns 排序
                columns.sort(Comparator.comparing(Column::getSort));
                if (RenderContentType.TABLE == renderContent.type()) {
                    tableContentList.add(new Content(renderContent.name(), field.getName(), renderContent.sort(), columns,renderContent.detailsKey(),renderContent.detailsValue()));
                } else if (RenderContentType.DESC == renderContent.type()) {
                    descContentList.add(new Content(renderContent.name(), field.getName(), renderContent.sort(), columns,renderContent.detailsKey(),renderContent.detailsValue()));
                } else if (RenderContentType.IMG == renderContent.type()) {
                    imgContentList.add(new Content(renderContent.name(), field.getName(), renderContent.sort(), columns,renderContent.detailsKey(),renderContent.detailsValue()));
                }
            }
        }
        // 排序
        tableContentList.sort(Comparator.comparing(Content::getSort));
        descContentList.sort(Comparator.comparing(Content::getSort));
        imgContentList.sort(Comparator.comparing(Content::getSort));
        form.setTableContentList(tableContentList);
        form.setDescContentList(descContentList);
        form.setImgContentList(imgContentList);
    }

    /**
     * 获取 Column 相关信息
     */
    private List<Column> getColumns(Class<?> clz, String filterValue) {
        List<Column> columns = new ArrayList<>();
        // 字段
        Field[] fields = clz.getDeclaredFields();
        // Field RenderColumn
        for (Field field : fields) {
            field.setAccessible(true);
            RenderColumn renderColumn = (RenderColumn) findAnnotation(field.getAnnotations(), RenderColumn.class);
            if (renderColumn != null && isFilter(renderColumn, filterValue)) {
                columns.add(new Column(renderColumn.name(), field.getName(), renderColumn.sort(),
                        renderColumn.group(), renderColumn.groupName(), renderColumn.isSpecialSisplay(),
                        renderColumn.isRow(), renderColumn.isDataType() ));
            }
        }
        // Method RenderColumn
        Method[] methods = clz.getDeclaredMethods();
        for (Method method : methods) {
            method.setAccessible(true);
            RenderColumn renderColumn = (RenderColumn) findAnnotation(method.getAnnotations(), RenderColumn.class);
            if (renderColumn != null && isFilter(renderColumn, filterValue)) {
                String fieldName = renderColumn.field();
                if (StringUtils.isBlank(fieldName)) {
                    fieldName = method.getName();
                    fieldName = fieldName.replaceFirst("get", "");
                    fieldName = fieldName.replaceFirst(fieldName.substring(0, 1), fieldName.substring(0, 1).toLowerCase());
                }
                columns.add( new Column( renderColumn.name(), fieldName, renderColumn.sort(),
                        renderColumn.group(), renderColumn.groupName(), renderColumn.isSpecialSisplay() ,
                        renderColumn.isRow(), renderColumn.isDataType()) );
            }
        }
        return columns;
    }


    /**
     * find Annotation
     */
    private Annotation findAnnotation(Annotation[] annotations, Class<?> clz) {
        for (Annotation anno : annotations) {
            if (anno.annotationType().equals(clz)) {
                return anno;
            }
        }
        return null;
    }

    /**
     * getFilterValue
     */
    private String getFilterValue(Class<?> clz, Object result) throws IllegalAccessException {
        Field[] fields = clz.getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            for (Annotation anno : field.getAnnotations()) {
                if (anno.annotationType().equals(RenderFilterField.class)) {
                    return (String) field.get(result);
                }
            }
        }
        return null;
    }

    /**
     * isFilter
     */
    private boolean isFilter(RenderColumn renderColumn, String filterValue) {
        if (filterValue == null) {
            return true;
        } else {
            for (String val : renderColumn.filter()) {
                if ("ALL".equals(val) || filterValue.equals(val)) {
                    return true;
                }
            }
            return false;
        }
    }

}
